// ESP32 + HP4067 (CD74HC4067) 多路电位器采集 + 蓝牙串口输出（合法 JSON）
// - 避开启动相关脚；S0~S3 采用 16/17/18/19
// - 公共模拟口接 ADC1 引脚（如 GPIO33）
// - EN 低电平使能；若 EN 已接地，可将 MUX_EN 注释并去掉相关代码

#include <Arduino.h>
#include <ArduinoJson.h>
#include "BluetoothSerial.h"

BluetoothSerial SerialBT;

// ================== 引脚定义 ==================
#define MUX_S0   16
#define MUX_S1   17
#define MUX_S2   18
#define MUX_S3   19
#define MUX_EN   21      // 若 EN 与 GND 直连，可注释掉本行并移除相关代码
#define MUX_SIG  33      // ADC1 建议用 GPIO32~39 之一，这里用 GPIO33

// 读数相关
#define ADC_BITS         12           // ESP32 默认 12 位
#define ADC_MAX_VALUE    ((1 << ADC_BITS) - 1) // 4095
#define ADC_ATTEN        ADC_11db     // 0~3.3V
#define SAMPLE_COUNT     4            // 多次采样平均
#define SETTLE_US        8            // 通道切换后的稳定时间（微秒）
#define SEND_CHANNELS    16           // 发送前 N 个通道（1~16）

// ================== 工具函数 ==================
void toPrint(const String &msg) {
  Serial.println(msg);
  SerialBT.println(msg);
}
void toPrint(int v) {
  String s = String(v);
  Serial.println(s);
  SerialBT.println(s);
}

// ================== 硬件初始化 ==================
void initPins() {
  pinMode(MUX_S0, OUTPUT);
  pinMode(MUX_S1, OUTPUT);
  pinMode(MUX_S2, OUTPUT);
  pinMode(MUX_S3, OUTPUT);
  pinMode(MUX_SIG, INPUT);
#ifdef MUX_EN
  pinMode(MUX_EN, OUTPUT);
  digitalWrite(MUX_EN, LOW);  // 低电平使能
#endif
}

void setupADC() {
  analogSetPinAttenuation(MUX_SIG, ADC_ATTEN);
  analogReadResolution(ADC_BITS); // 0~4095
}

// ================== MUX 控制与采样 ==================
inline void muxSelect(uint8_t ch) {
  digitalWrite(MUX_S0, ch & 0x01);
  digitalWrite(MUX_S1, (ch >> 1) & 0x01);
  digitalWrite(MUX_S2, (ch >> 2) & 0x01);
  digitalWrite(MUX_S3, (ch >> 3) & 0x01);
}

int readChannel(uint8_t ch, uint8_t samples = SAMPLE_COUNT) {
  muxSelect(ch);
  delayMicroseconds(SETTLE_US);   // 切换后稳定
  (void)analogRead(MUX_SIG);      // 丢弃一次，降低残留电压影响

  uint32_t acc = 0;
  for (uint8_t i = 0; i < samples; i++) {
    acc += analogRead(MUX_SIG);
  }
  return (int)(acc / samples);
}

// ================== 信息与打包 ==================
void getInfo(const String &source) {
  StaticJsonDocument<128> doc;
  doc["source"] = source;
  doc["type"]   = "control";
  String out;
  serializeJson(doc, out);
  toPrint(out);
}

void readAllAndSend(uint8_t count = SEND_CHANNELS) {
  if (count > 16) count = 16;
  StaticJsonDocument<768> doc;
  JsonArray arr = doc.createNestedArray("adc");  // adc: [ch0, ch1, ...]
  for (uint8_t ch = 0; ch < count; ch++) {
    arr.add(readChannel(ch));
  }
  String out;
  serializeJson(doc, out);
  toPrint(out);
}

// 兼容你原来的两路调试输出
void getServo() {
  toPrint("0:");
  toPrint(readChannel(0));
  toPrint("1:");
  toPrint(readChannel(1));
}

// ================== Arduino 标准入口 ==================
void setup() {
  Serial.begin(115200);
  SerialBT.begin("HUMAN_CONTROL");
  initPins();
  setupADC();
  getInfo("boot");
}

void loop() {
  // 方式 A：一次发前 SEND_CHANNELS 路（默认 16 路）JSON
  readAllAndSend(SEND_CHANNELS);

  // 方式 B：仅调试 0/1 两路（需要时取消注释）
  // getServo();

  delay(10);  // 约 100Hz；按需调整
}
